﻿Imports System.Runtime.Serialization

<DebuggerDisplay("{ToString()}")>
<DataContract(Namespace:="urn:VBF.CompilerModel.Scanner")>
Public Structure CharRange
    Implements IEquatable(Of CharRange)

    <DataMember()>
    Public ReadOnly Min As Char
    <DataMember()>
    Public ReadOnly Max As Char

    Public ReadOnly Property Length As Integer
        Get
            Return AscW(Max) - AscW(Min) + 1
        End Get
    End Property

    Public Sub New(ByVal min As Char, ByVal max As Char)
        CodeContract.Requires(min <= max, "max")

        Me.Min = min
        Me.Max = max
    End Sub

    Public Overrides Function Equals(ByVal obj As Object) As Boolean
        If obj Is Nothing Then Return False
        If Not TypeOf obj Is CharRange Then Return False

        Return Equals(DirectCast(obj, CharRange))
    End Function

    Public Overloads Function Equals(ByVal other As CharRange) As Boolean Implements IEquatable(Of CharRange).Equals
        Return Min = other.Min AndAlso Max = other.Max
    End Function

    Public Overrides Function GetHashCode() As Integer
        Return (Min.GetHashCode() << 1) Xor Max.GetHashCode
    End Function

    Public Overrides Function ToString() As String
        Dim minDisplay = If(Char.IsLetterOrDigit(Min) OrElse Char.IsSymbol(Min), Min.ToString, String.Format("\u{0:X4}", AscW(Min)))
        Dim maxDisplay = If(Char.IsLetterOrDigit(Min) OrElse Char.IsSymbol(Max), Max.ToString, String.Format("\u{0:X4}", AscW(Max)))
        Return String.Format("[{0}-{1}]", minDisplay, maxDisplay)
    End Function

    Public Function IsSubRangeOf(ByVal other As CharRange) As Boolean
        Return Min >= other.Min AndAlso Max <= other.Max
    End Function

    Public Function Contains(ByVal c As Char) As Boolean
        Return c >= Min AndAlso c <= Max
    End Function

    'Predefined ranges

    Public Shared ReadOnly All As CharRange = New CharRange(Char.MinValue, Char.MaxValue)

End Structure
